package com.jblv.frame.config;

import com.jblv.frame.config.annotation.RefreshScope;
import com.jblv.frame.config.utils.ConfigBootstrapHttpUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.PriorityOrdered;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;

/**
 * @author happyonion.yangtao
 * @version 1.0
 * @title ConfigBeanPostProcessor
 * @projectName jblv-frame
 * @packageName com.jblv.frame.config
 * @description TODO
 * @date Create at 2020/9/7 17:18
 * @since jdk1.8
 */
public class ConfigBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered {

    private final static Logger logger = LoggerFactory.getLogger(ConfigBeanPostProcessor.class);

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return super.postProcessAfterInitialization(bean, beanName);
    }

    /**
     * 操作属性，如变更属性值，但是只能对于XML形式有效
     * @param pvs
     * @param pds
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        try {
            RefreshScope scope = bean.getClass().getAnnotation(RefreshScope.class);
            if (scope == null) {
                return pvs;
            }
            if (RefreshScopeBeanHolder.checkScopeBean(beanName)) {
                return pvs;
            }
            Field[] declaredFields2;
            Field[] declaredFields = declaredFields2 = bean.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields2) {
                Value value = declaredField.getAnnotation(Value.class);
                if (value != null) {
                    String key = value.value().trim();
                    String k = "";
                    if (key.startsWith("${") && key.endsWith("}")) {
                        key = key.replace("${", "").replace("}", "");
                        k = key.split(":")[0];
                    }
                    String v = ConfigCenterProperties.getProperty(k);
                    if (!StringUtils.isBlank(v)) {
                        declaredField.setAccessible(true);
                        declaredField.set(bean, v);
                    }
                }
            }
            return pvs;
        }
        catch (Exception e) {
            logger.error(e.getMessage(), (Throwable)e);
            return pvs;
        }
    }


    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition rootBeanDefinition, Class<?> beanType, String beanName) {
        if (rootBeanDefinition.isSingleton()) {
            RefreshScopeBeanHolder.putScopeBean(beanName);
        }
    }

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    }
}
